/**
 * 
 */
package pruebas.tiendaOl.dominio.casosUso;

import java.io.Serializable;
import java.util.logging.Logger;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.ApplicationException;
import javax.enterprise.context.ConversationScoped;
import javax.inject.Inject;

import pruebas.tiendaOl.dominio.SesionCliente;
import pruebas.tiendaOl.dominio.entidades.Carrito;
import pruebas.tiendaOl.dominio.entidades.Cliente;
import pruebas.tiendaOl.dominio.entidades.Gondola;
import pruebas.tiendaOl.dominio.entidades.TipoArticulo;
import pruebas.tiendaOl.dominio.repositorios.RepoCliente;

import com.intelap.fabricaciones.InterceptorTransaccional.Transaccional;
import com.intelap.fabricaciones.UnidadTrabajo;

/**En esta clase estan los casos de uso correspondientes a agente cliente.
 * ADVERTENCIA: el context scope de esta clase debe ser el mismo que, o estar contenido por, el context scope de {@link UnidadTrabajo}.
 * No se usa esta misma clase para sustentar (determinar el ciclo de vida) de la {@link UnidadTrabajo} porque, si se pretende evitar que los usuarios de la {@link UnidadTrabajo} dependan de esta clase, la instancia de {@link UnidadTrabajo} deberia exponerse mediante un productor; pero como esta clase tiene campos inyectados que dependen de la instancia de {@link UnidadTrabajo} que expondría dicho productor, el éxito de la inicialización dependería del orden en que CDI inyecta los campos, cosa que (si no me equivoco) no esta especificada.    
 *  @author ggpollit */
@ConversationScoped
public class CasosUsoCliente implements Serializable {
	@Inject
	private SesionCliente sesionCliente;
	@Inject
	private transient RepoCliente repoCliente;
	@Inject
	private UnidadTrabajo ut;


	private Cliente clienteLogueado = null;
	public Cliente getClienteLogueado() {
		if (clienteLogueado == null) {
			clienteLogueado = repoCliente.buscarCliente(sesionCliente.getNombreUsuarioClienteLogueado());
			if (clienteLogueado == null)
				throw new SesionInvalida("Aparentemente ha cambiado el nombre de usuario del cliente logueado.");
		}
		return clienteLogueado;
	}

	private Carrito carrito = null;
	public Carrito getCarrito() {
		if (carrito == null) {
			this.carrito = getClienteLogueado().getCarrito();
		}
		return this.carrito;
	}

	@Inject
	private Gondola gondola;
	public Gondola getGondola() {
		return gondola;
	}


	@Transaccional
	public int ponerArticulosEnCarrito(TipoArticulo tipoArticulo, int cantidad) {
		try {
			int cantidadTomada = getGondola().sacarArticulos(tipoArticulo, cantidad);
			getCarrito().ponerArticulos(tipoArticulo, cantidadTomada);
			return cantidadTomada;
		} catch (Exception e) {
			this.ut.abortar();
			throw e;
		}
	}

	@Transaccional
	public int sacarArticulosDeCarrito(TipoArticulo tipoArticulo, int cantidad) {
		try {
			int cantidadTomada = getCarrito().sacarArticulos(tipoArticulo, cantidad);
			getGondola().ponerArticulos(tipoArticulo, cantidadTomada);
			return cantidadTomada;
		} catch (Exception e) {
			this.ut.abortar();
			throw e;
		}
	}

	/** Quien ataje esta excepcion debe invalidar la sesion */
	@ApplicationException(rollback = true)
	public class SesionInvalida extends RuntimeException {
		public SesionInvalida(String mensaje) {
			super(mensaje);
		}
	}

	//// Debug ////
	@Inject
	private Logger logger;
	@PostConstruct
	void postConstruct() {
		logger.info("postConstruct CasosUsoCliente#" + System.identityHashCode(this));
	}
	@PreDestroy
	void preDestroy() {
		logger.info("preDestroy CasosUsoCliente#"+ System.identityHashCode(this));
	}
}
